/**
 * 聊天应用本地存储工具类
 * 用于管理聊天历史、媒体文件和用户数据的本地缓存
 */

// 类型定义
interface ChatHistory {
  username: string;
  messages: Record<string, MessageObject[]>;
  timestamp: number;
}

interface MessageObject {
  messageId?: string;
  username: string;
  roomId: string;
  roomType?: 'group' | 'private';
  content: string;
  time: number | string;
  messageType: 'text' | 'image' | 'voice' | 'video' | 'file';
  duration?: number;
  fileInfo?: {
    name: string;
    size: number;
    type: string;
  };
  imageInfo?: {
    width: number;
    height: number;
  };
  videoInfo?: {
    width: number;
    height: number;
    duration: number;
  };
}

interface FileCache {
  [key: string]: string;
}

interface UserData {
  username: string;
  preferences?: Record<string, any>;
  timestamp: number;
}

interface StorageInfo {
  total: number;
  used: number;
  available: number;
}

// 存储键名定义
const KEYS = {
  CHAT_HISTORY: 'chat_history',
  FILES: 'chat_files',
  USER_DATA: 'chat_user_data',
}

// 存储配置
const CONFIG = {
  FILE_CACHE_MAX_SIZE: 10 * 1024 * 1024, // 10MB文件缓存上限
  MESSAGE_LIMIT_PER_ROOM: 100, // 每个房间最多保存消息数
  PURGE_INTERVAL: 24 * 60 * 60 * 1000, // 24小时自动清理一次
}

/**
 * 保存聊天历史
 * @param {string} username - 用户名
 * @param {object} messages - 消息对象，格式为 {roomId: [messageObj, ...], ...}
 */
export function saveChatHistory(username: string, messages: Record<string, MessageObject[]>): boolean {
  try {
    // 创建副本，防止修改原对象
    const historyToSave: Record<string, MessageObject[]> = {}
    
    // 限制每个房间保存的消息数量
    Object.keys(messages).forEach(roomId => {
      historyToSave[roomId] = messages[roomId].slice(-CONFIG.MESSAGE_LIMIT_PER_ROOM)
    })
    
    // 构造保存对象
    const data: ChatHistory = {
      username,
      messages: historyToSave,
      timestamp: Date.now(),
    }
    
    // 保存到本地存储
    localStorage.setItem(KEYS.CHAT_HISTORY, JSON.stringify(data))
    
    return true
  } catch (error) {
    console.error('保存聊天历史失败:', error)
    return false
  }
}

/**
 * 加载聊天历史
 * @returns {object|null} 聊天历史对象，如果不存在则返回null
 */
export function loadChatHistory(): ChatHistory | null {
  try {
    const data = localStorage.getItem(KEYS.CHAT_HISTORY)
    return data ? JSON.parse(data) : null
  } catch (error) {
    console.error('加载聊天历史失败:', error)
    return null
  }
}

/**
 * 保存媒体文件到缓存
 * @param {object} message - 消息对象
 * @returns {boolean} 是否保存成功
 */
export function saveFileToCache(message: MessageObject): boolean {
  // 只处理媒体类型的消息
  if (!['image', 'voice', 'video', 'file'].includes(message.messageType) || !message.content) {
    return false
  }
  
  try {
    // 读取现有缓存
    let files: FileCache = {}
    const fileCache = localStorage.getItem(KEYS.FILES)
    if (fileCache) {
      files = JSON.parse(fileCache)
    }
    
    // 为文件创建唯一键
    const fileKey = getFileKey(message)
    
    // 保存文件内容
    files[fileKey] = message.content
    
    // 检查缓存大小
    const filesJson = JSON.stringify(files)
    if (filesJson.length < CONFIG.FILE_CACHE_MAX_SIZE) {
      localStorage.setItem(KEYS.FILES, filesJson)
      return true
    } else {
      console.warn('文件缓存已达到容量限制，执行清理')
      // 清理最旧的文件，直到缓存大小满足要求
      pruneFileCache(files, message)
      return false
    }
  } catch (error) {
    console.error('保存文件到缓存失败:', error)
    return false
  }
}

/**
 * 从文件缓存中获取文件
 * @param {object} message - 消息对象
 * @returns {string|null} 文件内容，如果不存在则返回null
 */
export function getFileFromCache(message: MessageObject): string | null {
  try {
    const fileCache = localStorage.getItem(KEYS.FILES)
    if (!fileCache) return null
    
    const files: FileCache = JSON.parse(fileCache)
    const fileKey = getFileKey(message)
    
    return files[fileKey] || null
  } catch (error) {
    console.error('从缓存获取文件失败:', error)
    return null
  }
}

/**
 * 清理文件缓存
 * @param {object} messages - 所有消息对象
 * @returns {boolean} 是否清理成功
 */
export function cleanupFileCache(messages: Record<string, MessageObject[]>): boolean {
  try {
    const fileCache = localStorage.getItem(KEYS.FILES)
    if (!fileCache) return true
    
    const files: FileCache = JSON.parse(fileCache)
    const existingFiles = new Set<string>()
    
    // 收集所有消息中引用的文件
    Object.values(messages).flat().forEach(message => {
      if (['image', 'voice', 'video', 'file'].includes(message.messageType)) {
        const fileKey = getFileKey(message)
        existingFiles.add(fileKey)
      }
    })
    
    // 保留仍在使用的文件
    const newFiles: FileCache = {}
    Object.keys(files).forEach(fileKey => {
      if (existingFiles.has(fileKey)) {
        newFiles[fileKey] = files[fileKey]
      }
    })
    
    // 更新缓存
    localStorage.setItem(KEYS.FILES, JSON.stringify(newFiles))
    return true
  } catch (error) {
    console.error('清理文件缓存失败:', error)
    return false
  }
}

/**
 * 保存用户数据
 * @param {object} userData - 用户数据对象
 * @returns {boolean} 是否保存成功
 */
export function saveUserData(userData: Partial<UserData>): boolean {
  try {
    localStorage.setItem(KEYS.USER_DATA, JSON.stringify({
      ...userData,
      timestamp: Date.now()
    }))
    return true
  } catch (error) {
    console.error('保存用户数据失败:', error)
    return false
  }
}

/**
 * 加载用户数据
 * @returns {object|null} 用户数据对象，如果不存在则返回null
 */
export function loadUserData(): UserData | null {
  try {
    const data = localStorage.getItem(KEYS.USER_DATA)
    return data ? JSON.parse(data) : null
  } catch (error) {
    console.error('加载用户数据失败:', error)
    return null
  }
}

/**
 * 清除所有聊天数据
 * @returns {boolean} 是否清除成功
 */
export function clearAllChatData(): boolean {
  try {
    localStorage.removeItem(KEYS.CHAT_HISTORY)
    localStorage.removeItem(KEYS.FILES)
    return true
  } catch (error) {
    console.error('清除聊天数据失败:', error)
    return false
  }
}

// 辅助函数：获取文件的唯一键
function getFileKey(message: MessageObject): string {
  return `${message.messageType}_${message.time}_${message.username}`
}

// 辅助函数：清理文件缓存，保留需要的文件
function pruneFileCache(files: FileCache, newMessage: MessageObject): boolean {
  try {
    // 按时间排序文件(假设键中包含ISO日期)
    const sortedKeys = Object.keys(files).sort((a, b) => {
      const timeA = a.split('_')[1]
      const timeB = b.split('_')[1]
      return new Date(timeA).valueOf() - new Date(timeB).valueOf()
    })
    
    // 移除最旧的文件，直到有足够空间
    const newKey = getFileKey(newMessage)
    const newFiles: FileCache = {}
    
    // 保留最新的文件和当前要添加的文件
    for (let i = Math.floor(sortedKeys.length / 2); i < sortedKeys.length; i++) {
      newFiles[sortedKeys[i]] = files[sortedKeys[i]]
    }
    newFiles[newKey] = newMessage.content
    
    // 保存精简后的缓存
    localStorage.setItem(KEYS.FILES, JSON.stringify(newFiles))
    return true
  } catch (error) {
    console.error('清理文件缓存失败:', error)
    return false
  }
}

// 检测可用存储空间
export function getAvailableStorage(): StorageInfo {
  try {
    // 尝试计算大致的可用空间
    let testData = ''
    let totalSpace = 0
    const storageLimit = 10 * 1024 * 1024 // 10MB，localStorage的理论上限
    const step = 1024 * 10 // 每次增加10KB
    
    // 用一个暂存的键测试
    const testKey = 'storage_test'
    
    try {
      // 逐步增加数据大小，直到失败
      while (testData.length < storageLimit) {
        testData += new Array(step).fill('A').join('')
        localStorage.setItem(testKey, testData)
        totalSpace = testData.length
      }
    } catch (e) {
      // 达到存储限制
    } finally {
      // 清理测试数据
      localStorage.removeItem(testKey)
    }
    
    // 计算当前已使用的空间
    let usedSpace = 0
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i)
      if (key) {
        const item = localStorage.getItem(key)
        usedSpace += item ? item.length : 0
      }
    }
    
    return {
      total: totalSpace,
      used: usedSpace,
      available: totalSpace - usedSpace
    }
  } catch (error) {
    console.error('计算存储空间失败:', error)
    return {
      total: 0,
      used: 0,
      available: 0
    }
  }
} 